﻿Public Class ExifTags : Inherits SortedList(Of Integer, ExifTag)

	Private Shared Function GetComponentsConfig(ByVal bytes As Byte()) As String
		Dim s As String = ""
		Dim vals As String() = New String() {"", "Y", "Cb", "Cr", "R", "G", _
		 "B"}

		For Each b As Byte In bytes
			s += vals(b)
		Next

		Return s
	End Function

	Sub New()
		Add(&H100, New ExifTag(&H100, "width", "Image width"))
		Add(&H101, New ExifTag(&H101, "height", "Image height"))
		Add(&H0, New ExifTag(&H0, "GPSVersionID", "GPS tag version"))
		Add(&H5, New ExifTag(&H5, "GPSAltitudeRef", "Altitude reference"))
		Add(&H111, New ExifTag(&H111, "StripOffsets", "Image data location"))
		Add(&H116, New ExifTag(&H116, "RowsPerStrip", "Number of rows per strip"))
		Add(&H117, New ExifTag(&H117, "StripByteCounts", "Bytes per compressed strip"))
		Add(&HA002, New ExifTag(&HA002, "PixelXDimension", "Valid image width"))
		Add(&HA003, New ExifTag(&HA003, "PixelYDimension", "Valid image height"))
		Add(&H102, New ExifTag(&H102, "BitsPerSample", "Number of bits per component"))
		Add(&H103, New ExifTag(&H103, "Compression", "Compression scheme"))
		Add(&H106, New ExifTag(&H106, "PhotometricInterpretation", "Pixel composition"))
		Add(&H112, New ExifTag(&H112, "Orientation", "Orientation of image"))
		Add(&H115, New ExifTag(&H115, "SamplesPerPixel", "Number of components"))
		Add(&H11C, New ExifTag(&H11C, "PlanarConfiguration", "Image data arrangement"))
		Add(&H212, New ExifTag(&H212, "YCbCrSubSampling", "Subsampling ratio of Y to C"))
		Add(&H213, New ExifTag(&H213, "YCbCrPositioning", "Y and C positioning"))
		Add(&H128, New ExifTag(&H128, "ResolutionUnit", "Unit of X and Y resolution"))
		Add(&H12D, New ExifTag(&H12D, "TransferFunction", "Transfer function"))
		Add(&HA001, New ExifTag(&HA001, "ColorSpace", "Color space information"))
		Add(&H8822, New ExifTag(&H8822, "ExposureProgram", "Exposure program"))
		Add(&H8827, New ExifTag(&H8827, "ISOSpeedRatings", "ISO speed rating"))
		Add(&H9207, New ExifTag(&H9207, "MeteringMode", "Metering mode"))
		Add(&H9208, New ExifTag(&H9208, "LightSource", "Light source"))
		Add(&H9209, New ExifTag(&H9209, "Flash", "Flash"))
		Add(&H9214, New ExifTag(&H9214, "SubjectArea", "Subject area"))
		Add(&HA210, New ExifTag(&HA210, "FocalPlaneResolutionUnit", "Focal plane resolution unit"))
		Add(&HA214, New ExifTag(&HA214, "SubjectLocation", "Subject location"))
		Add(&HA217, New ExifTag(&HA217, "SensingMethod", "Sensing method"))
		Add(&HA401, New ExifTag(&HA401, "CustomRendered", "Custom image processing"))
		Add(&HA402, New ExifTag(&HA402, "ExposureMode", "Exposure mode"))
		Add(&HA403, New ExifTag(&HA403, "WhiteBalance", "White balance"))
		Add(&HA405, New ExifTag(&HA405, "FocalLengthIn35mmFilm", "Focal length in 35 mm film"))
		Add(&HA406, New ExifTag(&HA406, "SceneCaptureType", "Scene capture type"))
		Add(&HA408, New ExifTag(&HA408, "Contrast", "Contrast"))
		Add(&HA409, New ExifTag(&HA409, "Saturation", "Saturation"))
		Add(&HA40A, New ExifTag(&HA40A, "Sharpness", "Sharpness"))
		Add(&HA40C, New ExifTag(&HA40C, "SubjectDistanceRange", "Subject distance range"))
		Add(&H1E, New ExifTag(&H1E, "GPSDifferential", "GPS differential correction"))
		Add(&H9201, New ExifTag(&H9201, "ShutterSpeedValue", "Shutter speed"))
		Add(&H9203, New ExifTag(&H9203, "BrightnessValue", "Brightness"))
		Add(&H9204, New ExifTag(&H9204, "ExposureBiasValue", "Exposure bias"))
		Add(&H201, New ExifTag(&H201, "JPEGInterchangeFormat", "Offset to JPEG SOI"))
		Add(&H202, New ExifTag(&H202, "JPEGInterchangeFormatLength", "Bytes of JPEG data"))
		Add(&H11A, New ExifTag(&H11A, "XResolution", "Image resolution in width direction"))
		Add(&H11B, New ExifTag(&H11B, "YResolution", "Image resolution in height direction"))
		Add(&H13E, New ExifTag(&H13E, "WhitePoint", "White point chromaticity"))
		Add(&H13F, New ExifTag(&H13F, "PrimaryChromaticities", "Chromaticities of primaries"))
		Add(&H211, New ExifTag(&H211, "YCbCrCoefficients", "Color space transformation matrix coefficients"))
		Add(&H214, New ExifTag(&H214, "ReferenceBlackWhite", "Pair of black and white reference values"))
		Add(&H9102, New ExifTag(&H9102, "CompressedBitsPerPixel", "Image compression mode"))
		Add(&H829A, New ExifTag(&H829A, "ExposureTime", "Exposure time"))
		Add(&H829D, New ExifTag(&H829D, "FNumber", "F number"))
		Add(&H9202, New ExifTag(&H9202, "ApertureValue", "Aperture"))
		Add(&H9205, New ExifTag(&H9205, "MaxApertureValue", "Maximum lens aperture"))
		Add(&H9206, New ExifTag(&H9206, "SubjectDistance", "Subject distance"))
		Add(&H920A, New ExifTag(&H920A, "FocalLength", "Lens focal length"))
		Add(&HA20B, New ExifTag(&HA20B, "FlashEnergy", "Flash energy"))
		Add(&HA20E, New ExifTag(&HA20E, "FocalPlaneXResolution", "Focal plane X resolution"))
		Add(&HA20F, New ExifTag(&HA20F, "FocalPlaneYResolution", "Focal plane Y resolution"))
		Add(&HA215, New ExifTag(&HA215, "ExposureIndex", "Exposure index"))
		Add(&HA404, New ExifTag(&HA404, "DigitalZoomRatio", "Digital zoom ratio"))
		Add(&HA407, New ExifTag(&HA407, "GainControl", "Gain control"))
		Add(&H2, New ExifTag(&H2, "GPSLatitude", "Latitude"))
		Add(&H4, New ExifTag(&H4, "GPSLongitude", "Longitude"))
		Add(&H6, New ExifTag(&H6, "GPSAltitude", "Altitude"))
		Add(&H7, New ExifTag(&H7, "GPSTimeStamp", "GPS time (atomic clock)"))
		Add(&HB, New ExifTag(&HB, "GPSDOP", "Measurement precision"))
		Add(&HD, New ExifTag(&HD, "GPSSpeed", "Speed of GPS receiver"))
		Add(&HF, New ExifTag(&HF, "GPSTrack", "Direction of movement"))
		Add(&H11, New ExifTag(&H11, "GPSImgDirection", "Direction of image"))
		Add(&H14, New ExifTag(&H14, "GPSDestLatitude", "Latitude of destination"))
		Add(&H16, New ExifTag(&H16, "GPSDestLongitude", "Longitude of destination"))
		Add(&H18, New ExifTag(&H18, "GPSDestBearing", "Bearing of destination"))
		Add(&H1A, New ExifTag(&H1A, "GPSDestDistance", "Distance to destination"))
		Add(&H132, New ExifTag(&H132, "datetime", "File change date and time"))
		Add(&H10E, New ExifTag(&H10E, "ImageDescription", "Image title"))
		Add(&H10F, New ExifTag(&H10F, "make", "Image input equipment manufacturer"))
		Add(&H110, New ExifTag(&H110, "model", "Image input equipment model"))
		Add(&H131, New ExifTag(&H131, "Software", "Software used"))
		Add(&H13B, New ExifTag(&H13B, "Artist", "Person who created the image"))
		Add(&H8298, New ExifTag(&H8298, "Copyright", "Copyright holder"))
		Add(&HA004, New ExifTag(&HA004, "RelatedSoundFile", "Related audio file"))
		Add(&H9003, New ExifTag(&H9003, "datetime", "Date and time of original data generation"))
		Add(&H9004, New ExifTag(&H9004, "DateTimeDigitized", "Date and time of digital data generation"))
		Add(&H9290, New ExifTag(&H9290, "SubSecTime", "DateTime subseconds"))
		Add(&H9291, New ExifTag(&H9291, "SubSecTimeOriginal", "DateTimeOriginal subseconds"))
		Add(&H9292, New ExifTag(&H9292, "SubSecTimeDigitized", "DateTimeDigitized subseconds"))
		Add(&HA420, New ExifTag(&HA420, "ImageUniqueID", "Unique image ID"))
		Add(&H8824, New ExifTag(&H8824, "SpectralSensitivity", "Spectral sensitivity"))
		Add(&H1, New ExifTag(&H1, "GPSLatitudeRef", "North or South Latitude"))
		Add(&H3, New ExifTag(&H3, "GPSLongitudeRef", "East or West Longitude"))
		Add(&H8, New ExifTag(&H8, "GPSSatellites", "GPS satellites used for measurement"))
		Add(&H9, New ExifTag(&H9, "GPSStatus", "GPS receiver status"))
		Add(&HA, New ExifTag(&HA, "GPSMeasureMode", "GPS measurement mode"))
		Add(&HC, New ExifTag(&HC, "GPSSpeedRef", "Speed unit"))
		Add(&HE, New ExifTag(&HE, "GPSTrackRef", "Reference for direction of movement"))
		Add(&H10, New ExifTag(&H10, "GPSImgDirectionRef", "Reference for direction of image"))
		Add(&H12, New ExifTag(&H12, "GPSMapDatum", "Geodetic survey data used"))
		Add(&H13, New ExifTag(&H13, "GPSDestLatitudeRef", "Reference for latitude of destination"))
		Add(&H15, New ExifTag(&H15, "GPSDestLongitudeRef", "Reference for longitude of destination"))
		Add(&H17, New ExifTag(&H17, "GPSDestBearingRef", "Reference for bearing of destination"))
		Add(&H19, New ExifTag(&H19, "GPSDestDistanceRef", "Reference for distance to destination"))
		Add(&H1D, New ExifTag(&H1D, "GPSDateStamp", "GPS date"))
		Add(&H8828, New ExifTag(&H8828, "OECF", "Optoelectric conversion factor"))
		Add(&HA20C, New ExifTag(&HA20C, "SpatialFrequencyResponse", "Spatial frequency response"))
		Add(&HA300, New ExifTag(&HA300, "FileSource", "File source"))
		Add(&HA301, New ExifTag(&HA301, "SceneType", "Scene type"))
		Add(&HA302, New ExifTag(&HA302, "CFAPattern", "CFA pattern"))
		Add(&HA40B, New ExifTag(&HA40B, "DeviceSettingDescription", "Device settings description"))
		Add(&H9000, New ExifTag(&H9000, "ExifVersion", "Exif version"))
		Add(&HA000, New ExifTag(&HA000, "FlashpixVersion", "Supported Flashpix version"))
		Add(&H9101, New ExifTag(&H9101, "ComponentsConfiguration", "Meaning of each component"))
		Add(&H927C, New ExifTag(&H927C, "MakerNote", "Manufacturer notes"))
		Add(&H9286, New ExifTag(&H9286, "UserComment", "User comments"))
		Add(&H1B, New ExifTag(&H1B, "GPSProcessingMethod", "Name of GPS processing method"))
		Add(&H1C, New ExifTag(&H1C, "GPSAreaInformation", "Name of GPS area"))
	End Sub

	Private Const THUMBNAIL_DATA As Integer = 20507

	Sub Read(ByVal Image As Image)
      For Each Prop In Image.PropertyItems
         Try
            If Prop.Id = THUMBNAIL_DATA Then
               'Dim Buffer As Byteend select = Item.Value
               'Dim ThumbStream As New MemoryStream(Buffer.Length)
               'ThumbStream.Write(Buffer, 0, Buffer.Length)
               'Dim Thumb = Image.FromStream(ThumbStream)
               'Thumb.Save(CentralThumbName, System.Drawing.Imaging.ImageFormat.Jpeg)
               'My.Computer.FileSystem.CopyFile(CentralThumbName, LocalThumbName, True)
               'If Not Studio.Thumbs.ContainsKey(File) Then Studio.Thumbs.Add(File, Thumb)
            ElseIf ContainsKey(Prop.Id) Then
               Dim Value As String = ""
               If Prop.Type = &H1 Then
                  If Prop.Value.Length = 4 Then
                     Value = "Version " & Prop.Value(0).ToString() & "." & Prop.Value(1).ToString()
                  ElseIf Prop.Id = &H5 AndAlso Prop.Value(0) = 0 Then
                     Value = "Sea level"
                  Else
                     Value = Prop.Value(0).ToString()
                  End If
               ElseIf Prop.Type = &H2 Then

                  Value = System.Text.Encoding.ASCII.GetString(Prop.Value).Trim(ControlChars.NullChar)

                  If Prop.Id = &H1 OrElse Prop.Id = &H13 Then
                     If Value = "N" Then
                        Value = "North latitude"
                     ElseIf Value = "S" Then
                        Value = "South latitude"
                     Else
                        Value = "reserved"
                     End If
                  End If

                  If Prop.Id = &H3 OrElse Prop.Id = &H15 Then
                     If Value = "E" Then
                        Value = "East longitude"
                     ElseIf Value = "W" Then
                        Value = "West longitude"
                     Else
                        Value = "reserved"
                     End If
                  End If

                  If Prop.Id = &H9 Then
                     If Value = "A" Then
                        Value = "Measurement in progress"
                     ElseIf Value = "V" Then
                        Value = "Measurement Interoperability"
                     Else
                        Value = "reserved"
                     End If
                  End If

                  If Prop.Id = &HA Then
                     If Value = "2" Then
                        Value = "2-dimensional measurement"
                     ElseIf Value = "3" Then
                        Value = "3-dimensional measurement"
                     Else
                        Value = "reserved"
                     End If
                  End If

                  If Prop.Id = &HC OrElse Prop.Id = &H19 Then
                     If Value = "K" Then
                        Value = "Kilometers per hour"
                     ElseIf Value = "M" Then
                        Value = "Miles per hour"
                     ElseIf Value = "N" Then
                        Value = "Knots"
                     Else
                        Value = "reserved"
                     End If
                  End If

                  If Prop.Id = &HE OrElse Prop.Id = &H10 OrElse Prop.Id = &H17 Then
                     If Value = "T" Then
                        Value = "True direction"
                     ElseIf Value = "M" Then
                        Value = "Magnetic direction"
                     Else
                        Value = "reserved"
                     End If
                  End If
               ElseIf Prop.Type = &H3 Then

                  Dim uintval As UInt16 = BitConverter.ToUInt16(Prop.Value, 0)

                  ' orientation // lookup table					
                  Select Case Prop.Id
                     Case &H8827
                        ' ISO speed rating
                        Value = "ISO-" & uintval.ToString()
                        Exit Select
                     Case &HA217
                        ' sensing method
                        If True Then
                           Select Case uintval
                              Case 1
                                 Value = "Not defined"
                                 Exit Select
                              Case 2
                                 Value = "One-chip color area sensor"
                                 Exit Select
                              Case 3
                                 Value = "Two-chip color area sensor"
                                 Exit Select
                              Case 4
                                 Value = "Three-chip color area sensor"
                                 Exit Select
                              Case 5
                                 Value = "Color sequential area sensor"
                                 Exit Select
                              Case 7
                                 Value = "Trilinear sensor"
                                 Exit Select
                              Case 8
                                 Value = "Color sequential linear sensor"
                                 Exit Select
                              Case Else
                                 Value = " reserved"
                                 Exit Select
                           End Select
                        End If
                        Exit Select
                     Case &H8822
                        ' Exposure program
                        Select Case uintval
                           Case 0
                              Value = "Not defined"
                              Exit Select
                           Case 1
                              Value = "Manual"
                              Exit Select
                           Case 2
                              Value = "Normal program"
                              Exit Select
                           Case 3
                              Value = "Aperture priority"
                              Exit Select
                           Case 4
                              Value = "Shutter priority"
                              Exit Select
                           Case 5
                              Value = "Creative program (biased toward depth of field)"
                              Exit Select
                           Case 6
                              Value = "Action program (biased toward fast shutter speed)"
                              Exit Select
                           Case 7
                              Value = "Portrait mode (for closeup photos with the background out of focus)"
                              Exit Select
                           Case 8
                              Value = "Landscape mode (for landscape photos with the background in focus)"
                              Exit Select
                           Case Else
                              Value = "reserved"
                              Exit Select
                        End Select
                        Exit Select
                     Case &H9207
                        ' metering mode
                        Select Case uintval
                           Case 0
                              Value = "unknown"
                              Exit Select
                           Case 1
                              Value = "Average"
                              Exit Select
                           Case 2
                              Value = "Center Weighted Average"
                              Exit Select
                           Case 3
                              Value = "Spot"
                              Exit Select
                           Case 4
                              Value = "MultiSpot"
                              Exit Select
                           Case 5
                              Value = "Pattern"
                              Exit Select
                           Case 6
                              Value = "Partial"
                              Exit Select
                           Case 255
                              Value = "Other"
                              Exit Select
                           Case Else
                              Value = "reserved"
                              Exit Select
                        End Select
                        Exit Select
                     Case &H9208
                        ' Light source
                        If True Then
                           Select Case uintval
                              Case 0
                                 Value = "unknown"
                                 Exit Select
                              Case 1
                                 Value = "Daylight"
                                 Exit Select
                              Case 2
                                 Value = "Fluorescent"
                                 Exit Select
                              Case 3
                                 Value = "Tungsten (incandescent light)"
                                 Exit Select
                              Case 4
                                 Value = "Flash"
                                 Exit Select
                              Case 9
                                 Value = "Fine weather"
                                 Exit Select
                              Case 10
                                 Value = "Cloudy weather"
                                 Exit Select
                              Case 11
                                 Value = "Shade"
                                 Exit Select
                              Case 12
                                 Value = "Daylight fluorescent (D 5700 – 7100K)"
                                 Exit Select
                              Case 13
                                 Value = "Day white fluorescent (N 4600 – 5400K)"
                                 Exit Select
                              Case 14
                                 Value = "Cool white fluorescent (W 3900 – 4500K)"
                                 Exit Select
                              Case 15
                                 Value = "White fluorescent (WW 3200 – 3700K)"
                                 Exit Select
                              Case 17
                                 Value = "Standard light A"
                                 Exit Select
                              Case 18
                                 Value = "Standard light B"
                                 Exit Select
                              Case 19
                                 Value = "Standard light C"
                                 Exit Select
                              Case 20
                                 Value = "D55"
                                 Exit Select
                              Case 21
                                 Value = "D65"
                                 Exit Select
                              Case 22
                                 Value = "D75"
                                 Exit Select
                              Case 23
                                 Value = "D50"
                                 Exit Select
                              Case 24
                                 Value = "ISO studio tungsten"
                                 Exit Select
                              Case 255
                                 Value = "ISO studio tungsten"
                                 Exit Select
                              Case Else
                                 Value = "other light source"
                                 Exit Select
                           End Select
                        End If
                        Exit Select
                     Case &H9209
                        ' Flash
                        If True Then
                           Select Case uintval
                              Case &H0
                                 Value = "Flash did not fire"
                                 Exit Select
                              Case &H1
                                 Value = "Flash fired"
                                 Exit Select
                              Case &H5
                                 Value = "Strobe return light not detected"
                                 Exit Select
                              Case &H7
                                 Value = "Strobe return light detected"
                                 Exit Select
                              Case &H9
                                 Value = "Flash fired, compulsory flash mode"
                                 Exit Select
                              Case &HD
                                 Value = "Flash fired, compulsory flash mode, return light not detected"
                                 Exit Select
                              Case &HF
                                 Value = "Flash fired, compulsory flash mode, return light detected"
                                 Exit Select
                              Case &H10
                                 Value = "Flash did not fire, compulsory flash mode"
                                 Exit Select
                              Case &H18
                                 Value = "Flash did not fire, auto mode"
                                 Exit Select
                              Case &H19
                                 Value = "Flash fired, auto mode"
                                 Exit Select
                              Case &H1D
                                 Value = "Flash fired, auto mode, return light not detected"
                                 Exit Select
                              Case &H1F
                                 Value = "Flash fired, auto mode, return light detected"
                                 Exit Select
                              Case &H20
                                 Value = "No flash function"
                                 Exit Select
                              Case &H41
                                 Value = "Flash fired, red-eye reduction mode"
                                 Exit Select
                              Case &H45
                                 Value = "Flash fired, red-eye reduction mode, return light not detected"
                                 Exit Select
                              Case &H47
                                 Value = "Flash fired, red-eye reduction mode, return light detected"
                                 Exit Select
                              Case &H49
                                 Value = "Flash fired, compulsory flash mode, red-eye reduction mode"
                                 Exit Select
                              Case &H4D
                                 Value = "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected"
                                 Exit Select
                              Case &H4F
                                 Value = "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected"
                                 Exit Select
                              Case &H59
                                 Value = "Flash fired, auto mode, red-eye reduction mode"
                                 Exit Select
                              Case &H5D
                                 Value = "Flash fired, auto mode, return light not detected, red-eye reduction mode"
                                 Exit Select
                              Case &H5F
                                 Value = "Flash fired, auto mode, return light detected, red-eye reduction mode"
                                 Exit Select
                              Case Else
                                 Value = "reserved"
                                 Exit Select
                           End Select
                        End If
                        Exit Select
                     Case &H128
                        'ResolutionUnit
                        If True Then
                           Select Case uintval
                              Case 2
                                 Value = "Inch"
                                 Exit Select
                              Case 3
                                 Value = "Centimeter"
                                 Exit Select
                              Case Else
                                 Value = "No Unit"
                                 Exit Select
                           End Select
                        End If
                        Exit Select
                     Case &HA409
                        ' Saturation
                        If True Then
                           Select Case uintval
                              Case 0
                                 Value = "Normal"
                                 Exit Select
                              Case 1
                                 Value = "Low saturation"
                                 Exit Select
                              Case 2
                                 Value = "High saturation"
                                 Exit Select
                              Case Else
                                 Value = "Reserved"
                                 Exit Select
                           End Select
                        End If
                        Exit Select

                     Case &HA40A
                        ' Sharpness
                        If True Then
                           Select Case uintval
                              Case 0
                                 Value = "Normal"
                                 Exit Select
                              Case 1
                                 Value = "Soft"
                                 Exit Select
                              Case 2
                                 Value = "Hard"
                                 Exit Select
                              Case Else
                                 Value = "Reserved"
                                 Exit Select
                           End Select
                        End If
                        Exit Select
                     Case &HA408
                        ' Contrast
                        If True Then
                           Select Case uintval
                              Case 0
                                 Value = "Normal"
                                 Exit Select
                              Case 1
                                 Value = "Soft"
                                 Exit Select
                              Case 2
                                 Value = "Hard"
                                 Exit Select
                              Case Else
                                 Value = "Reserved"
                                 Exit Select
                           End Select
                        End If
                        Exit Select
                     Case &H103
                        ' Compression
                        If True Then
                           Select Case uintval
                              Case 1
                                 Value = "Uncompressed"
                                 Exit Select
                              Case 6
                                 Value = "JPEG compression (thumbnails only)"
                                 Exit Select
                              Case Else
                                 Value = "Reserved"
                                 Exit Select
                           End Select
                        End If
                        Exit Select
                     Case &H106
                        ' PhotometricInterpretation
                        If True Then
                           Select Case uintval
                              Case 2
                                 Value = "RGB"
                                 Exit Select
                              Case 6
                                 Value = "YCbCr"
                                 Exit Select
                              Case Else
                                 Value = "Reserved"
                                 Exit Select
                           End Select
                        End If
                        Exit Select
                     Case &H112
                        ' Orientation
                        If True Then
                           Select Case uintval
                              Case 1
                                 Value = "The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side."
                                 Exit Select
                              Case 2
                                 Value = "The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side."
                                 Exit Select
                              Case 3
                                 Value = "The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side."
                                 Exit Select
                              Case 4
                                 Value = "The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side."
                                 Exit Select
                              Case 5
                                 Value = "The 0th row is the visual left-hand side of the image, and the 0th column is the visual top."
                                 Exit Select
                              Case 6
                                 Value = "The 0th row is the visual right-hand side of the image, and the 0th column is the visual top."
                                 Exit Select
                              Case 7
                                 Value = "The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom."
                                 Exit Select
                              Case 8
                                 Value = "The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom."
                                 Exit Select
                              Case Else
                                 Value = "Reserved"
                                 Exit Select
                           End Select
                        End If
                        Exit Select
                     Case &H213
                        ' YCbCrPositioning
                        If True Then
                           Select Case uintval
                              Case 1
                                 Value = "centered"
                                 Exit Select
                              Case 6
                                 Value = "co-sited"
                                 Exit Select
                              Case Else
                                 Value = "Reserved"
                                 Exit Select
                           End Select
                        End If
                        Exit Select
                     Case &HA001
                        ' ColorSpace
                        If True Then
                           Select Case uintval
                              Case 1
                                 Value = "sRGB"
                                 Exit Select
                              Case &HFFFF
                                 Value = "Uncalibrated"
                                 Exit Select
                              Case Else
                                 Value = "Reserved"
                                 Exit Select
                           End Select
                        End If
                        Exit Select
                     Case &HA401
                        ' CustomRendered
                        If True Then
                           Select Case uintval
                              Case 0
                                 Value = "Normal process"
                                 Exit Select
                              Case 1
                                 Value = "Custom process"
                                 Exit Select
                              Case Else
                                 Value = "Reserved"
                                 Exit Select
                           End Select
                        End If
                        Exit Select
                     Case &HA402
                        ' ExposureMode
                        If True Then
                           Select Case uintval
                              Case 0
                                 Value = "Auto exposure"
                                 Exit Select
                              Case 1
                                 Value = "Manual exposure"
                                 Exit Select
                              Case 2
                                 Value = "Auto bracket"
                                 Exit Select
                              Case Else
                                 Value = "Reserved"
                                 Exit Select
                           End Select
                        End If
                        Exit Select
                     Case &HA403
                        ' WhiteBalance
                        If True Then
                           Select Case uintval
                              Case 0
                                 Value = "Auto white balance"
                                 Exit Select
                              Case 1
                                 Value = "Manual white balance"
                                 Exit Select
                              Case Else
                                 Value = "Reserved"
                                 Exit Select
                           End Select
                        End If
                        Exit Select
                     Case &HA406
                        ' SceneCaptureType
                        If True Then
                           Select Case uintval
                              Case 0
                                 Value = "Standard"
                                 Exit Select
                              Case 1
                                 Value = "Landscape"
                                 Exit Select
                              Case 2
                                 Value = "Portrait"
                                 Exit Select
                              Case 3
                                 Value = "Night scene"
                                 Exit Select
                              Case Else
                                 Value = "Reserved"
                                 Exit Select
                           End Select
                        End If
                        Exit Select

                     Case &HA40C
                        ' SubjectDistanceRange
                        If True Then
                           Select Case uintval
                              Case 0
                                 Value = "unknown"
                                 Exit Select
                              Case 1
                                 Value = "Macro"
                                 Exit Select
                              Case 2
                                 Value = "Close view"
                                 Exit Select
                              Case 3
                                 Value = "Distant view"
                                 Exit Select
                              Case Else
                                 Value = "Reserved"
                                 Exit Select
                           End Select
                        End If
                        Exit Select
                     Case &H1E
                        ' GPSDifferential
                        If True Then
                           Select Case uintval
                              Case 0
                                 Value = "Measurement without differential correction"
                                 Exit Select
                              Case 1
                                 Value = "Differential correction applied"
                                 Exit Select
                              Case Else
                                 Value = "Reserved"
                                 Exit Select
                           End Select
                        End If
                        Exit Select
                     Case &HA405
                        ' FocalLengthIn35mmFilm
                        Value = uintval.ToString() & " mm"
                        Exit Select
                     Case Else
                        '
                        Value = uintval.ToString()
                        Exit Select
                  End Select
               ElseIf Prop.Type = &H4 Then
                  Value = BitConverter.ToUInt32(Prop.Value, 0).ToString()
               ElseIf Prop.Type = &H5 Then

                  Dim rat As New URational(Prop.Value)

                  Select Case Prop.Id
                     Case &H9202
                        ' ApertureValue
                        Value = "F/" & Math.Round(Math.Pow(Math.Sqrt(2), rat.ToDouble()), 2).ToString()
                        Exit Select
                     Case &H9205
                        ' MaxApertureValue
                        Value = "F/" & Math.Round(Math.Pow(Math.Sqrt(2), rat.ToDouble()), 2).ToString()
                        Exit Select
                     Case &H920A
                        ' FocalLength
                        Value = rat.ToDouble().ToString() & " mm"
                        Exit Select
                     Case &H829D
                        ' F-number
                        Value = "F/" & rat.ToDouble().ToString()
                        Exit Select
                     Case &H11A
                        ' Xresolution
                        Value = rat.ToDouble().ToString()
                        Exit Select
                     Case &H11B
                        ' Yresolution
                        Value = rat.ToDouble().ToString()
                        Exit Select
                     Case &H829A
                        ' ExposureTime
                        Value = rat.ToString() & " sec"
                        Exit Select
                     Case &H2
                        ' GPSLatitude                                
                        Value = New GPSRational(Prop.Value).ToString()
                        Exit Select
                     Case &H4
                        ' GPSLongitude
                        Value = New GPSRational(Prop.Value).ToString()
                        Exit Select
                     Case &H6
                        ' GPSAltitude
                        Value = rat.ToDouble() & " meters"
                        Exit Select
                     Case &HA404
                        ' Digital Zoom Ratio
                        Value = rat.ToDouble().ToString()
                        If Value = "0" Then
                           Value = "none"
                        End If
                        Exit Select
                     Case &HB
                        ' GPSDOP
                        Value = rat.ToDouble().ToString()
                        Exit Select
                     Case &HD
                        ' GPSSpeed
                        Value = rat.ToDouble().ToString()
                        Exit Select
                     Case &HF
                        ' GPSTrack
                        Value = rat.ToDouble().ToString()
                        Exit Select
                     Case &H11
                        ' GPSImgDir
                        Value = rat.ToDouble().ToString()
                        Exit Select
                     Case &H14
                        ' GPSDestLatitude
                        Value = New GPSRational(Prop.Value).ToString()
                        Exit Select
                     Case &H16
                        ' GPSDestLongitude
                        Value = New GPSRational(Prop.Value).ToString()
                        Exit Select
                     Case &H18
                        ' GPSDestBearing
                        Value = rat.ToDouble().ToString()
                        Exit Select
                     Case &H1A
                        ' GPSDestDistance
                        Value = rat.ToDouble().ToString()
                        Exit Select
                     Case &H7
                        ' GPSTimeStamp                                
                        Value = New GPSRational(Prop.Value).ToString(":")
                        Exit Select
                     Case Else

                        Value = rat.ToString()
                        Exit Select

                  End Select
               ElseIf Prop.Type = &H7 Then
                  Select Case Prop.Id
                     Case &HA300
                        'FileSource
                        If True Then
                           If Prop.Value(0) = 3 Then
                              Value = "DSC"
                           Else
                              Value = "reserved"
                           End If
                           Exit Select
                        End If
                     Case &HA301
                        'SceneType
                        If Prop.Value(0) = 1 Then
                           Value = "A directly photographed image"
                        Else
                           Value = "reserved"
                        End If
                        Exit Select
                     Case &H9000
                        ' Exif Version
                        Value = System.Text.Encoding.ASCII.GetString(Prop.Value).Trim(ControlChars.NullChar)
                        Exit Select
                     Case &HA000
                        ' Flashpix Version
                        Value = System.Text.Encoding.ASCII.GetString(Prop.Value).Trim(ControlChars.NullChar)
                        If Value = "0100" Then
                           Value = "Flashpix Format Version 1.0"
                        Else
                           Value = "reserved"
                        End If
                        Exit Select
                     Case &H9101
                        'ComponentsConfiguration
                        Value = GetComponentsConfig(Prop.Value)
                        Exit Select
                     Case &H927C
                        'MakerNote
                        Value = System.Text.Encoding.ASCII.GetString(Prop.Value).Trim(ControlChars.NullChar)
                        Exit Select
                     Case &H9286
                        'UserComment
                        Value = System.Text.Encoding.ASCII.GetString(Prop.Value).Trim(ControlChars.NullChar)
                        Exit Select
                     Case &H1B
                        'GPS Processing Method
                        Value = System.Text.Encoding.ASCII.GetString(Prop.Value).Trim(ControlChars.NullChar)
                        Exit Select
                     Case &H1C
                        'GPS Area Info
                        Value = System.Text.Encoding.ASCII.GetString(Prop.Value).Trim(ControlChars.NullChar)
                        Exit Select
                     Case Else
                        Value = "-"
                        Exit Select
                  End Select
               ElseIf Prop.Type = &H9 Then
                  Value = BitConverter.ToInt32(Prop.Value, 0).ToString()
               ElseIf Prop.Type = &HA Then

                  Dim rat As New Rational(Prop.Value)

                  Select Case Prop.Id
                     Case &H9201
                        ' ShutterSpeedValue
                        Value = "1/" & Math.Round(Math.Pow(2, rat.ToDouble()), 2).ToString()
                        Exit Select
                     Case &H9203
                        ' BrightnessValue
                        Value = Math.Round(rat.ToDouble(), 4).ToString()
                        Exit Select
                     Case &H9204
                        ' ExposureBiasValue
                        Value = Math.Round(rat.ToDouble(), 2).ToString() & " eV"
                        Exit Select
                     Case Else
                        Value = rat.ToString()
                        Exit Select
                  End Select
               End If

               Me(Prop.Id).Value = Value

            End If
         Catch ex As Exception

         End Try
      Next
	End Sub

End Class

Public Class ExifTag

	Public ID As Integer, Name As String, Definition As String, Value As Object

	Sub New(ByVal ID As Integer, ByVal Name As String, ByVal Definition As String)
		Me.ID = ID
		Me.Name = Name
		Me.Definition = Definition
	End Sub

End Class

Friend NotInheritable Class URational
	Private _num As UInt32
	Private _denom As UInt32

	Public Sub New(ByVal bytes As Byte())
		Dim n As Byte() = New Byte(3) {}
		Dim d As Byte() = New Byte(3) {}
		Array.Copy(bytes, 0, n, 0, 4)
		Array.Copy(bytes, 4, d, 0, 4)
		_num = BitConverter.ToUInt32(n, 0)
		_denom = BitConverter.ToUInt32(d, 0)
	End Sub

	Public Function ToDouble() As Double
		Return Math.Round(Convert.ToDouble(_num) / Convert.ToDouble(_denom), 2)
	End Function

	Public Overrides Function ToString() As String
		Return Me.ToString("/")
	End Function

	Public Overloads Function ToString(ByVal separator As String) As String
		Return _num.ToString() & separator & _denom.ToString()
	End Function
End Class

Friend NotInheritable Class GPSRational
	Private _hours As Rational
	Private _minutes As Rational
	Private _seconds As Rational

	Public Property Hours() As Rational
		Get
			Return _hours
		End Get
		Set(ByVal value As Rational)
			_hours = value
		End Set
	End Property
	Public Property Minutes() As Rational
		Get
			Return _minutes
		End Get
		Set(ByVal value As Rational)
			_minutes = value
		End Set
	End Property
	Public Property Seconds() As Rational
		Get
			Return _seconds
		End Get
		Set(ByVal value As Rational)
			_seconds = value
		End Set
	End Property

	Public Sub New(ByVal bytes As Byte())
		Dim h As Byte() = New Byte(7) {}
		Dim m As Byte() = New Byte(7) {}
		Dim s As Byte() = New Byte(7) {}

		Array.Copy(bytes, 0, h, 0, 8)
		Array.Copy(bytes, 8, m, 0, 8)
		Array.Copy(bytes, 16, s, 0, 8)

		_hours = New Rational(h)
		_minutes = New Rational(m)
		_seconds = New Rational(s)
	End Sub

	Public Overrides Function ToString() As String
		Return _hours.ToDouble() & "° " & _minutes.ToDouble() & "' " & _seconds.ToDouble() & """"
	End Function

	Public Overloads Function ToString(ByVal separator As String) As String
		Return _hours.ToDouble() & separator & _minutes.ToDouble() & separator & _seconds.ToDouble()
	End Function
End Class

Friend NotInheritable Class Rational
	Private _num As Int32
	Private _denom As Int32

	Public Sub New(ByVal bytes As Byte())
		Dim n As Byte() = New Byte(3) {}
		Dim d As Byte() = New Byte(3) {}
		Array.Copy(bytes, 0, n, 0, 4)
		Array.Copy(bytes, 4, d, 0, 4)
		_num = BitConverter.ToInt32(n, 0)
		_denom = BitConverter.ToInt32(d, 0)
	End Sub

	Public Function ToDouble() As Double
		Return Math.Round(Convert.ToDouble(_num) / Convert.ToDouble(_denom), 2)
	End Function

	Public Overloads Function ToString(ByVal separator As String) As String
		Return _num.ToString() & separator & _denom.ToString()
	End Function

	Public Overrides Function ToString() As String
		Return Me.ToString("/")
	End Function
End Class
